﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using ZedGraph;

namespace QuantumFractals
{
    public enum HistoriogramTypes { Density, MinTime, MaxTime }

    public partial class HistoriogramForm : Form
    {
        public MainForm MainForm { get { return Application.OpenForms[0] as MainForm; } }
        private SortedDictionary<int, int> historiogram = null;
        private SortedDictionary<int, int> formula = null;

        public HistoriogramForm()
        {
            InitializeComponent();
        }

        private int GetMaxY()
        {
            int maxY = 0;
            foreach (int k in historiogram.Keys)
                maxY = Math.Max(maxY, historiogram[k]);
            return maxY;
        }

        private int GetMaxDensity()
        {
            return MainForm.Renderer.CalcSummary().ForObserver(
                MainForm.GetObserver(comObserver.Text));
        }

        private void DrawHistoriogram()
        {
            Cursor tempCursor = Cursor;
            Cursor = Cursors.WaitCursor;
            Application.DoEvents();
            historiogram = MainForm.Renderer.Historiogram.ForObserver(
                MainForm.GetObserver(comObserver.Text));
            MethodInfo method = Evaluator.AddFormula(comFormula.Text, "int",
                new Dictionary<string, string> { 
                    { "MAXX", GetMaxDensity().ToString() },
                    { "MAXY", GetMaxY().ToString() }},
                new Dictionary<string, string> { { "X", "double" } });
            formula = new SortedDictionary<int, int>();
            foreach (int k in historiogram.Keys)
            {
                object[] args = { (double)k };
                if (comFormula.Text.Trim() != "")
                    formula[k] = (int)method.Invoke(null, args);
                else
                    formula[k] = 0;
            }
            PointPairList list = new PointPairList();
            PointPairList list2 = new PointPairList();
            foreach (int k in historiogram.Keys)
            {
                list.Add(k, historiogram[k]);
                list2.Add(k, formula[k]);
            }
            Graph.GraphPane.Title.Text = MainForm.QuantumFractal.Name + " historiogram";
            Graph.GraphPane.XAxis.Title.Text = "Density";
            Graph.GraphPane.YAxis.Title.Text = "How many pixels";

            LineItem myCurve = null;
            LineItem myCurve2 = null;
            if (Graph.GraphPane.CurveList.Count >= 2)
            {
                Graph.GraphPane.CurveList[0].Points = list;
                Graph.GraphPane.CurveList[1].Points = list2;
            }
            else
            {
                myCurve = Graph.GraphPane.AddCurve("", list,
                    Color.Blue, SymbolType.Circle);
                myCurve.Symbol.Fill = new Fill(Color.White);
                myCurve2 = Graph.GraphPane.AddCurve("", list2,
                    Color.Red, SymbolType.Diamond);
            }
            Graph.AxisChange();
            Refresh();
            Cursor = tempCursor;
        }

        private void btnCopyToClipboard_Click(object sender, EventArgs e)
        {
            Clipboard.SetImage(Graph.GetImage());
            stMessage.Text = "Historiogram copied to clipboard";
        }

        private void btnPrint_Click(object sender, EventArgs e)
        {
            Graph.DoPrint();
            stMessage.Text = "Historiogram printed";
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            switch (MessageBox.Show("Export historiogram data as csv (yes) or image file (no)?", "Question",
                MessageBoxButtons.YesNoCancel))
            {
                case DialogResult.Yes:
                    Application.DoEvents();
                    if (saveFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        Application.DoEvents();
                        using (StreamWriter sw = new StreamWriter(saveFileDialog.FileName))
                        {
                            char separator = MainForm.GetSeparatorChar(
                                Properties.Settings.Default.CsvSeparator);
                            sw.WriteLine("Density" + separator + "How many" + separator + "Formula");
                            foreach (int k in historiogram.Keys)
                                sw.WriteLine(k.ToString() + separator + historiogram[k].ToString() +
                                    separator + formula[k].ToString());
                        }
                        stMessage.Text = "Historiogram saved as csv file";
                        if (MessageBox.Show("Open file in associated program?", "Question",
                            MessageBoxButtons.YesNo) == DialogResult.Yes)
                            Process.Start(saveFileDialog.FileName);
                    }
                    break;
                case DialogResult.No:
                    Application.DoEvents();
                    Graph.SaveAs("Historiogram");
                    stMessage.Text = "Historiogram saved as image";
                    if (MessageBox.Show("Open file in associated program?", "Question",
                        MessageBoxButtons.YesNo) == DialogResult.Yes)
                        Process.Start(Graph.SaveFileDialog.FileName);
                    break;
            }
        }

        private void Graph_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
                Graph.ZoomOut(Graph.GraphPane);
        }

        private void btnZoomPlus_Click(object sender, EventArgs e)
        {
            Graph.ZoomOut(Graph.GraphPane);
        }

        private void btnZoomMinus_Click(object sender, EventArgs e)
        {
            Graph.ZoomOut(Graph.GraphPane);
        }

        private void btnZoomAll_Click(object sender, EventArgs e)
        {
            Graph.ZoomOutAll(Graph.GraphPane);
        }

        private void comObserver_TextChanged(object sender, EventArgs e)
        {
            DrawHistoriogram();
        }

        private void comPalette_TextChanged(object sender, EventArgs e)
        {
            DrawHistoriogram();
        }

        private void comFormula_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                DrawHistoriogram();
        }

        private void btnDraw_Click(object sender, EventArgs e)
        {
            DrawHistoriogram();
        }

        private void btnFormulaBuilder_Click(object sender, EventArgs e)
        {
            using (FormulaForm form = new FormulaForm())
            {
                form.FormulaConstants = new Dictionary<string, string> { 
                    { "MAXX", GetMaxDensity().ToString() },
                    { "MAXY", GetMaxY().ToString() }};
                form.Formula = comFormula.Text;
                if (form.ShowDialog(this) == DialogResult.OK)
                {
                    comFormula.Text = form.Formula;
                    btnDraw_Click(sender, e);
                }
            }
            return;
        }

        private void HistoriogramForm_Paint(object sender, PaintEventArgs e)
        {
            comObserver.Text = MainForm.comObserver.Text;
        }

        private void btnInformation_Click(object sender, EventArgs e)
        {
            MaxPixelDensitySummary summary = MainForm.Renderer.CalcSummary();
            MessageBox.Show(String.Format(
                "Front maximum/sum of density: {0:### ### ### ###} / {1:### ### ### ###}\r\n" +
                "Back maximum/sum of density: {2:### ### ### ###} / {3:### ### ### ###}\r\n" +
                "Left maximum/sum of density: {4:### ### ### ###} / {5:### ### ### ###}\r\n" +
                "Right maximum/sum of density: {6:### ### ### ###}/{7:### ### ### ###}\r\n" +
                "Sum of all density (time): {8:### ### ### ### ###}",
                MainForm.Renderer.MaxPixelDensity.Front, MainForm.Renderer.SumPixelDensity.Front, 
                MainForm.Renderer.MaxPixelDensity.Back, MainForm.Renderer.SumPixelDensity.Back, 
                MainForm.Renderer.MaxPixelDensity.Left, MainForm.Renderer.SumPixelDensity.Left, 
                MainForm.Renderer.MaxPixelDensity.Right, MainForm.Renderer.SumPixelDensity.Right,
                MainForm.Renderer.SumPixelDensity.All),
                "Historiogram information", MessageBoxButtons.OK);

        }
    }
}
